/*-------------------------------------------------------------------------
 *
 * generic-acc.h
 *	  在 HPUX 上使用 HP 的 acc 时的原子操作支持
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * NOTES:
 *
 * 文档：
 * * 针对基于 Itanium 的 HP-UX 的内联汇编：
 *   http://h21007.www2.hp.com/portal/download/files/unprot/Itanium/inline_assem_ERS.pdf
 * * 在 Intel (R) Itanium (R) 架构和 PA-RISC 上实现自旋锁
 *   http://h21007.www2.hp.com/portal/download/files/unprot/itanium/spinlocks.pdf
 *
 * Itanium 仅支持一小组数字（6、-8、-4、-1、1、4、8、16）
 * 用于原子加/减，因此我们只是通过 atomics/generic.h 中的 compare_exchange 回退来
 * 实现所有操作，但 compare_exchange。
 *
 * src/include/port/atomics/generic-acc.h
 *
 * -------------------------------------------------------------------------
 */

#include <machine/sys/inline.h>

#define pg_compiler_barrier_impl()	_Asm_sched_fence()

#if defined(HAVE_ATOMICS)

/* IA64 始终具有 32/64 位原子操作 */

#define PG_HAVE_ATOMIC_U32_SUPPORT
typedef struct pg_atomic_uint32
{
	volatile uint32 value;
} pg_atomic_uint32;

#define PG_HAVE_ATOMIC_U64_SUPPORT
typedef struct pg_atomic_uint64
{
	/*
	 * 保证对齐为 64 位。请在 HP 网站上搜索“良好行为的应用程序限制”=>“数据对齐和数据共享”。 
	 * 不幸的是，URL 似乎不够稳定以便包括。
	 */
	volatile uint64 value;
} pg_atomic_uint64;


#define MINOR_FENCE (_Asm_fence) (_UP_CALL_FENCE | _UP_SYS_FENCE | \
								 _DOWN_CALL_FENCE | _DOWN_SYS_FENCE )

#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
static inline bool
pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
									uint32 *expected, uint32 newval)
{
	bool	ret;
	uint32	current;

	_Asm_mov_to_ar(_AREG_CCV, *expected, MINOR_FENCE);
	/*
	 * 我们需要一个屏障，而不仅仅是释放/获取语义。
	 */
	_Asm_mf();
	/*
	 * 注意：
	 * _DOWN_MEM_FENCE | _UP_MEM_FENCE 防止编译器重新排序
	 */
	current =  _Asm_cmpxchg(_SZ_W, /* word */
							_SEM_REL,
							&ptr->value,
							newval, _LDHINT_NONE,
							_DOWN_MEM_FENCE | _UP_MEM_FENCE);
	ret = current == *expected;
	*expected = current;
	return ret;
}


#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
static inline bool
pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
									uint64 *expected, uint64 newval)
{
	bool	ret;
	uint64	current;

	_Asm_mov_to_ar(_AREG_CCV, *expected, MINOR_FENCE);
	_Asm_mf();
	current =  _Asm_cmpxchg(_SZ_D, /* 双字 */
							_SEM_REL,
							&ptr->value,
							newval, _LDHINT_NONE,
							_DOWN_MEM_FENCE | _UP_MEM_FENCE);
	ret = current == *expected;
	*expected = current;
	return ret;
}

#undef MINOR_FENCE

#endif /* defined(HAVE_ATOMICS) */
